package com.chainwintel.prjmgmt.action;

import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ExceptionMapping;
import org.apache.struts2.convention.annotation.ExceptionMappings;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.chainwintel.prjmgmt.model.MenuItem;
import com.chainwintel.prjmgmt.model.User;
import com.chainwintel.prjmgmt.service.MenuItemMgr;
import com.chainwintel.prjmgmt.service.UserMgr;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;

@Component
@Results({
//	@Result(name = "input", location = "menuAssignment", type = "redirectAction"),
	@Result(name = "ERROR",location = "error.jsp"),
	@Result(name = "input", location = "prompt.jsp"),
	@Result(name = "menu-assignment", location = "menuAssignment2.jsp")
})
@ExceptionMappings({
	@ExceptionMapping(exception = "com.chainwintel.prjmgmt.exception.FailedToAssignOperationsException" ,result = "ERROR"),
	@ExceptionMapping(exception = "java.lang.RuntimeException", result = "ERROR"),
	@ExceptionMapping(exception = "java.lang.Exception" ,result = "ERROR")
})
public class MenuAssignmentAction extends ActionSupport implements Preparable {

	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = -6926234715079987451L;
	
	private static final Log log = LogFactory.getLog(MenuAssignmentAction.class);
	
	private List<MenuItem> available_menuList;
	
	private User user;
	
	private long userId;
	
	private MenuItem menuItem;
	
	private long menuId;
	
	private Set<MenuItem> assigned_menuList;
	
	@Autowired
	private MenuItemMgr menuItemMgr;
	
	@Autowired
	private UserMgr userMgr;

	public void prepare() throws Exception {
		// TODO Auto-generated method stub
		setAvailable_menuList(menuItemMgr.listMenus());
		
	}
	
	@Action("/menuAssignment")
	public String menuAssignment() {
		setUser(userMgr.find(getUserId()));
		setAssigned_menuList(getUser().getOperations());
		getAvailable_menuList().removeAll(getAssigned_menuList());
		
		setMenuItem(menuItemMgr.find(getMenuId()));
		
		
		return "menu-assignment";
	}
	
	@Action("/menu_assign")
	public String assign() {
		try {
			setUser(userMgr.find(getUserId()));
			setMenuItem(menuItemMgr.find(getMenuId()));
			menuItemMgr.doAssign(getUser(),getMenuItem());
			return "input";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("DataAccessException occurred", e);

			throw new RuntimeException("Operation failed.",e);
		}
	}
	
	@Action("/menu_unassign")
	public String unAssign() {
		try {
			setUser(userMgr.find(getUserId()));
			setMenuItem(menuItemMgr.find(getMenuId()));
			menuItemMgr.doUnassign(getUser(),getMenuItem());
			return "input";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("DataAccessException occurred", e);

			throw new RuntimeException("Operation failed.",e);
		}
	}

	public void setUser(User user) {
		this.user = user;
	}

	public User getUser() {
		return user;
	}

	public void setUserId(long userId) {
		this.userId = userId;
	}

	public long getUserId() {
		return userId;
	}

	public void setMenuItem(MenuItem menuItem) {
		this.menuItem = menuItem;
	}

	public MenuItem getMenuItem() {
		return menuItem;
	}

	public void setMenuId(long menuId) {
		this.menuId = menuId;
	}

	public long getMenuId() {
		return menuId;
	}

	public void setAssigned_menuList(Set<MenuItem> assigned_menuList) {
		this.assigned_menuList = assigned_menuList;
	}

	public Set<MenuItem> getAssigned_menuList() {
		return assigned_menuList;
	}

	public void setAvailable_menuList(List<MenuItem> available_menuList) {
		this.available_menuList = available_menuList;
	}

	public List<MenuItem> getAvailable_menuList() {
		return available_menuList;
	}

}
